#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import configparser
import strict_hwcfg


class FmScreen:

    @staticmethod
    def get_best_resolution_x(machineType, aspectRatio, diagnoal):
        if machineType == strict_hwcfg.MachineType.DESKTOP:
            if diagnoal == "27in":
                if aspectRatio in ["16:9", "16:10"]:
                    return 2560
                else:
                    # don't scale for unknown configuration
                    return None
            else:
                # don't scale for unknown configuration
                return None
        elif machineType in [strict_hwcfg.MachineType.LAPTOP, strict_hwcfg.MachineType.TABLET, strict_hwcfg.MachineType.CONVERTIBLE]:
            if diagnoal in ["13.3in", "12.3in"]:
                if aspectRatio in ["16:9", "16:10"]:
                    return 1920
                elif aspectRatio == "3:2":
                    return 1440
                else:
                    # don't scale for unknown configuration
                    return None
            else:
                # don't scale for unknown configuration
                return None
        elif machineType == strict_hwcfg.MachineType.HANDSET:
            if True:
                # FIXME: should have content
                return None
            else:
                # don't scale for unknown configuration
                return None
        elif machineType == strict_hwcfg.MachineType.WATCH:
            if True:
                # FIXME: should have content
                return None
            else:
                # don't scale for unknown configuration
                return None
        elif machineType == strict_hwcfg.MachineType.SERVER:
            # UI is not important, don't scale
            return None
        elif machineType == strict_hwcfg.MachineType.VM:
            # FIXME: UI is not important, don't scale, really
            return None
        elif machineType == strict_hwcfg.MachineType.CONTAINER:
            # FIXME: UI is not important, don't scale, really
            return None
        else:
            assert False


class FmWayFire:

    @staticmethod
    def get_template_config_filepath():
        return os.path.expanduser("~/.config/wayfire.ini")

    @classmethod
    def check_template_config_file(cls, bAutoFix=False):
        basicSectionList = [
            "core",
            "input",
            "input-device",
        ]

        def __checkPluginInList(pluginName):
            retModified = False
            if pluginName not in pluginList:
                if bAutoFix:
                    pluginList.append(pluginName)
                    pluginList.sort()
                    cfg.set("core", "plugins", " ".join(pluginList))
                    retModified = True
                else:
                    raise FmCheckException("%s plugin is not enabled in \"%s\"" % (pluginName, fullfn))
            return retModified

        def __checkSection(sectionName):
            retModified = False
            if not cfg.has_section(sectionName):
                if bAutoFix:
                    cfg.add_section(sectionName)
                    retModified = True
                else:
                    raise FmCheckException("section \"%s\" does not exist in \"%s\"" % (sectionName, fullfn))
            return retModified

        def __checkSectionOption(recordedOptionNames, sectionName, optionName, optionValue):
            retModified = False
            if cfg.get(sectionName, optionName, fallback=None) != optionValue:
                if bAutoFix:
                    cfg.set(sectionName, optionName, optionValue)
                    retModified = True
                else:
                    raise FmCheckException("invalid value of option \"%s\" in section \"autostart\" in \"%s\"" % (optionName, fullfn))
            recordedOptionNames.add(optionName)
            return retModified

        def __clearSetion(sectionName, recordedOptionNames):
            retModified = False
            for item in cfg.options(sectionName):
                if item not in recordedOptionNames:
                    if bAutoFix:
                        cfg.remove_option(sectionName, item)
                        retModified = True
                    else:
                        raise FmCheckException("redundant option \"%s\" in section \"%s\" in \"%s\"" % (item, sectionName, fullfn))
            return retModified

        fullfn = cls.get_template_config_filepath()
        cfg = configparser.ConfigParser(interpolation=None)
        cfg.read(fullfn)        # it is ok that fullfn does not exist here
        pluginList = [x.strip(" ") for x in cfg.get("core", "plugins", fallback="").split(" ") if x.strip(" ") != ""]
        bModified = False

        # basic sections
        for s in basicSectionList:
            if not cfg.has_section(s):
                if bAutoFix:
                    cfg.add_section(s)
                    bModified = True
                else:
                    raise FmCheckException("section \"%s\" does not exist in \"%s\"" % (s, fullfn))

        # autostart plugin
        if True:
            optionSet = set()
            bModified |= __checkPluginInList("autostart")
            bModified |= __checkSection("autostart")
            bModified |= __checkSectionOption(optionSet, "autostart", "autostart_wf_shell", "false")
            bModified |= __clearSetion("autostart", optionSet)

        # decoration plugin
        if True:
            optionSet = set([
                "active_color",
                "inactive_color",
                "border_size",
                "title_height",
                "button_order",
                "font",
                "ignore_views",
            ])
            bModified |= __checkPluginInList("decoration")
            bModified |= __checkSection("decoration")
            bModified |= __checkSectionOption(optionSet, "decoration", "border_size", "4")
            bModified |= __checkSectionOption(optionSet, "decoration", "title_height", "30")
            bModified |= __checkSectionOption(optionSet, "decoration", "button_order", "minimize maximize close")
            bModified |= __clearSetion("decoration", optionSet)

        # move plugin
        if True:
            optionSet = set([
                "activate",
                "enable_snap",
                "enable_snap_off",
                "snap_off_threshold",
                "quarter_snap_threshold",
                "join_views",
                "workspace_switch_after",
            ])
            bModified |= __checkPluginInList("move")
            bModified |= __checkSection("move")
            bModified |= __clearSetion("move", optionSet)

        # resize plugin
        if True:
            optionSet = set([
                "activate",
            ])
            bModified |= __checkPluginInList("resize")
            bModified |= __checkSection("resize")
            bModified |= __clearSetion("resize", optionSet)

        # remove redundant sections
        for item in cfg.sections():
            if item not in basicSectionList and item not in pluginList:
                if bAutoFix:
                    cfg.remove_section(item)
                    bModified = True
                else:
                    raise FmCheckException("redundant section \"%s\" in \"%s\"" % (item, fullfn))

        # write
        if bModified:
            os.makedirs(os.path.dirname(fullfn), exist_ok=True)
            with open(fullfn, 'w') as f:
                cfg.write(f)


class FmCheckException(Exception):

    def __init__(self, message):
        super(FmCheckException, self).__init__(message)
